package com.igeek.boot.config;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;

import com.igeek.boot.constant.RedisConstant;
import com.igeek.boot.entity.User;
import com.igeek.boot.exception.WisdomFactoryException;
import com.igeek.boot.utils.JwtHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;

/**
 * TODO
 *
 * @author chemin
 * @since 2024/1/3
 *
 * OncePerRequestFilter   认证过滤器
 * 作用：解析请求头中的token，并验证合法性。继承 OncePerRequestFilter 保证请求经过过滤器一次
 */
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter{

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    //过滤逻辑
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //登陆直接放行
        if(request.getRequestURI().equals("/wisdom_factory/user/login")
                ||request.getRequestURI().equals("/wisdom_factory/report/getBusinessReportData")
                ||request.getRequestURI().equals("/wisdom_factory/alipay")) {
            filterChain.doFilter(request, response);
            return;
        }

        //获取请求头中的token  若没有token也直接放行
        String token = request.getHeader("token");
        if(StrUtil.isEmpty(token)){
            //后续有对401 403 异常来进行处理
            filterChain.doFilter(request , response);
            return;
        }

        //JWT将token中的数据解析userId
        Integer userId;
        try{
            userId = JwtHelper.getUserId(token);
        }catch(Exception e){
            e.printStackTrace();
            throw new WisdomFactoryException("非法token!");
        }

        //从Redis中获取用户信息，若不存在直接抛出异常
        //login::user::1
        String tokenKey = RedisConstant.LOGIN_USER_TOKEN+"::"+userId;
        Object o = redisTemplate.opsForValue().get(tokenKey);
        if(Objects.isNull(o)){
            throw new WisdomFactoryException("Redis中未获取到管理员信息~");
        }
        //用户信息
        User user = JSONUtil.toBean(o.toString(), User.class);

        //若存在，则将Authentication对象（用户信息、已认证状态、角色权限信息）存入 SecurityContextHolder
        LoginUser loginUser = new LoginUser(user);
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser , null , loginUser.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);

        //放行
        filterChain.doFilter(request , response);
    }
}
